﻿using EnvDTE80;
using Microsoft.VisualStudio.GraphModel.CodeSchema;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Threading;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using VSAdditionalCommands.Helpers;
using static System.Net.Mime.MediaTypeNames;

namespace VSAdditionalCommands.ToolWindows.DublicateFilesToolWindow
{
    public partial class DublicateFilesToolWindowControl : UserControl
    {
        public DublicateFilesToolWindowControl()
        {
            this.InitializeComponent();
        }

        private async void btnRefreshPath_Click(object sender, RoutedEventArgs e)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
            var dte2 = await ServiceProvider.GetGlobalServiceAsync(typeof(SDTE)) as DTE2;
            var selectedItems = dte2.SelectedItems;
            if (selectedItems.MultiSelect || selectedItems.Count > 0)
            {
                var projects = dte2.ActiveSolutionProjects as Array;
                if (projects.Length > 0)
                {
                    var project = projects.GetValue(0) as EnvDTE.Project;
                    if (project != null)
                    {
                        var selectedItem = selectedItems.Item(1);
                        var filePath = selectedItem.ProjectItem.FileNames[0];
                        var projectDirectory = Path.GetDirectoryName(project.FileName);
                        var filePathDirectory = Path.GetDirectoryName(filePath);
                        if (projectDirectory == filePathDirectory)
                            txtDestSubPath.Text = "\\";
                        else
                            txtDestSubPath.Text = filePathDirectory.Replace(projectDirectory, "");
                    }
                }
            }
            else
            {
                txtDestSubPath.Text = string.Empty;
            }
        }

        string ApplyReplacements(string str)
        {
            string result = str;
            for (int i = 0; i < lstReplacements.Items.Count; i++)
            {
                var item = lstReplacements.Items[i] as ReplacementListBoxItem;
                if (item.KeepCaseFirstLetter)
                {
                    result = result.ReplaceKeepFirstLetterCase(item.FindText, item.ReplacementText);
                }
                else
                {
                    result = result.Replace(item.FindText, item.ReplacementText);
                }
            }
            return result;
        }

        private async void btnDublicate_Click(object sender, RoutedEventArgs e)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
            var dte2 = await ServiceProvider.GetGlobalServiceAsync(typeof(SDTE)) as DTE2;
            var selectedItems = dte2.SelectedItems;
            //путь относительно корня проекта
            txtDestSubPath.Text = txtDestSubPath.Text.Trim().Replace("/", "\\");
            if (txtDestSubPath.Text.EndsWith("\\"))
                txtDestSubPath.Text = txtDestSubPath.Text.Substring(0, txtDestSubPath.Text.Length - 1);

            if(txtFind.Text.Length > 0 
                && txtReplace.Text.Length > 0)
            {
                bool exists = false;
                foreach (var item in lstReplacements.Items)
                {
                    var replacementItem = item as ReplacementListBoxItem;
                    if (replacementItem.FindText == txtFind.Text 
                        && replacementItem.ReplacementText == txtReplace.Text)
                    {
                        exists = true;
                        break;
                    }
                }
                if(!exists) 
                {
                    AddReplacement();
                }
            }

            if (selectedItems.MultiSelect || selectedItems.Count > 0)
            {
                var firstItem = selectedItems.Item(1);
                //Get associated project item
                //If selectedItem is a project, then selectedItem.ProjectItem will be null,
                //and selectedItem.Project will not be null.
                if (firstItem.ProjectItem == null)
                    return;
                var firstItemProjectItem = firstItem.ProjectItem;
                if (firstItemProjectItem.ContainingProject == null)
                    return;
                //Get project for ProjectItem
                var project = firstItemProjectItem.ContainingProject;
                var projectPath = Path.GetDirectoryName(project.FileName);

                // Or get project object if selectedItem is a project
                //var sproject = selectedItem.Project;

                for (short i = 1; i <= selectedItems.Count; i++)
                {
                    //Get selected item
                    var selectedItem = selectedItems.Item(i);
                    var projectItem = selectedItem.ProjectItem;

                    //Is selectedItem a physical folder?
                    var isFolder = projectItem.Kind == EnvDTE.Constants.vsProjectItemKindPhysicalFolder;
                    if (!isFolder)
                    {
                        for (short j = 0; j < projectItem.FileCount; j++)
                        {
                            Debug.WriteLine(projectItem.FileNames[j]);

                            string destPath;
                            if(txtDestSubPath.Text == string.Empty)
                            {
                                destPath = Path.GetDirectoryName(project.FileName);
                            }
                            else if(txtDestSubPath.Text == "\\")
                            {
                                destPath = projectPath;
                            }
                            else
                            {
                                destPath = projectPath + txtDestSubPath.Text;
                            }

                            string fileName = Path.GetFileName(projectItem.FileNames[j]);
                            fileName = ApplyReplacements(fileName);
                            if (projectItem.FileNames[j] == destPath + "\\" + fileName)
                            {
                                var fileNameParts = fileName.Split('.');
                                fileNameParts[0] += "1";
                                fileName = string.Concat(fileNameParts[0], ".", fileNameParts[1]);
                            }
                            destPath += "\\" + fileName;
                            File.Copy(projectItem.FileNames[j], destPath);
                            string fileContent = File.ReadAllText(destPath);
                            fileContent = ApplyReplacements(fileContent);
                            File.WriteAllText(destPath, fileContent);
                            project.ProjectItems.AddFromFile(destPath);
                        }
                    }
                }
            }
        }

        private void btnAddReplacement_Click(object sender, RoutedEventArgs e)
        {
            AddReplacement();
        }

        private void btnDeleteReplacement_Click(object sender, RoutedEventArgs e)
        {
            if(lstReplacements.SelectedIndex > -1)
            {
                lstReplacements.Items.Remove(lstReplacements.SelectedItem);
                txtFind.Text = "";
                txtReplace.Text = "";
            }
        }

        private void AddReplacement()
        {
            if(txtFind.Text.Length > 0)
            {
                lstReplacements.Items.Add(new ReplacementListBoxItem() { 
                    Content = $"{txtFind.Text} -> {txtReplace.Text}", 
                    FindText = txtFind.Text, 
                    ReplacementText = txtReplace.Text,
                    KeepCaseFirstLetter = chkKeepCaseFirstLetter.IsChecked ?? false
                });
                lstReplacements.SelectedIndex = lstReplacements.Items.Count - 1;
            }
        }

        private void lstReplacements_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            var item = lstReplacements.SelectedItem as ReplacementListBoxItem;
            if (item != null)
            {
                txtFind.Text=item.FindText;
                txtReplace.Text = item.ReplacementText;
                chkKeepCaseFirstLetter.IsChecked = item.KeepCaseFirstLetter;
            }
        }

        private void DublicateFilesToolWindow_Loaded(object sender, RoutedEventArgs e)
        {
            btnRefreshPath_Click(null, null);
            txtFind.Focus();
        }
    }
}